const TABLEName = "share";
const { querySql, queryOne } = require("../utils/sql");
const { encrypt, decrypt } = require("../utils/crypto");
const { format } = require("../utils/moment");
const { setLog } = require("../utils/log.js");

const path = require("path");
const fs = require("fs");

const intformat = require("biguint-format"),
  FlakeId = require("flake-idgen");

const share = async (req, res) => {
  try {
    let { shareTime, accessPwd, fileId, filePath } = req.body;
    const id = intformat(new FlakeId().next(), "dec");
    const hash = encrypt(JSON.stringify({ id }));
    // console.log(hash);
    // console.log(decrypt(hash));
    // console.log({ shareTime, accessPwd, fileId, filePath });

    let obj = {
      shareTime,
      fileId,
      filePath,
      accessPwd,
      id: id,
      shareLink: "/share/" + hash,
    };
    if (accessPwd) {
      obj.accessPwd = accessPwd;
    }
    // console.log("11111111", obj);
    const sqlStr1 = `(${Object.keys(obj).join(", ")})`;
    let sqlStr2 = `(`;
    Object.values(obj).forEach((item, index) => {
      if (index < Object.values(obj).length - 1) {
        sqlStr2 += `'${item}', `;
      } else {
        sqlStr2 += `'${item}')`;
      }
    });
    let insertQuery = `insert into ${TABLEName}${sqlStr1} values${sqlStr2}`;
    let searchQuery = `select * from ${TABLEName} where fileId = '${fileId}'`;
    let updateQuery = `update ${TABLEName} set updateTime = '${format(
      new Date()
    )}', shareTime = '${shareTime}'`;
    if (accessPwd) {
      updateQuery += `, accessPwd = '${accessPwd}'`;
    }
    if (!accessPwd) {
      updateQuery += `, accessPwd = ''`;
    }
    updateQuery += ` where fileId = '${fileId}'`;
    // console.log("insertQuery",insertQuery);
    // console.log("searchQuery",searchQuery);
    // console.log("updateQuery", updateQuery);

    let data = await querySql(searchQuery);
    // console.log("data", data);

    if (data.length > 0) {
      let isHave = await querySql(updateQuery);
      // console.log("============", isHave);
      let data = await querySql(searchQuery);

      if (isHave.affectedRows === 1) {
        setLog(
          req.getToken()?.id,
          `用户${req.getToken()?.username}分享了文件id为：${fileId}的文件`
        );
        return res.json({
          code: 0,
          data: data.map((item) => {
            return { ...item, createTime: format(item.createTime) };
          }),
          msg: "创建成功。",
        });
      } else {
        return res.json({
          code: -1,
          data: null,
          msg: "更新失败。",
        });
      }
    } else {
      // console.log("没有查出share里面有和当前fileId相等的数据");

      querySql(insertQuery).then(async (ins) => {
        // console.log("ins", ins);
        if (ins || ins.affectedRows === 1) {
          querySql(searchQuery).then((ins) => {
            // console.log("ins", ins, ins.length);
            if (ins.length > 0) {
              setLog(
                req.getToken()?.id,
                `用户${req.getToken()?.username}分享了文件id为：${fileId}的文件`
              );
              res.json({
                code: 0,
                data: ins,
                msg: "创建成功。",
              });
            } else {
              res.json({
                code: -1,
                data: null,
                msg: "查询失败。",
              });
            }
          });
        } else {
          res.json({
            code: -1,
            data: null,
            msg: "写入失败。",
          });
        }
      });
    }
  } catch (err) {
    res.json({
      code: -1,
      data: null,
      msg: "创建失败。",
    });
  }
};

async function getShareFile(req, res) {
  try {
    let { params } = req.params;
    // console.log("req.params", req.params,req.query);

    let { id } = JSON.parse(decrypt(params));

    let search_share_Query = `select * from share where id = '${id}'`;
    // 查找一下文件表file_info里面的数据是否被删除了？
    let share_data = await querySql(search_share_Query);
    // console.log("data", share_data);
    if (!share_data || share_data?.length > 1) {
      return res.status(500).json({
        code: -1,
        msg: `未知错误。`,
      });
    }
    let { fileId, accessPwd, shareTime, createTime, filePath } = share_data[0];
    let difference_timestamp = null;
    if (shareTime) {
      difference_timestamp =
        new Date() - createTime > shareTime * 24 * 60 * 60 * 1000;
    }
    // console.log("difference_timestamp",difference_timestamp);
    if (difference_timestamp) {
      return res.status(403).json({
        code: -1,
        msg: `文件已过期。`,
      });
    }
    // console.log("accessPwd", accessPwd);

    if (accessPwd) {
  

      if (!req.query?.accessPwd || accessPwd != req.query?.accessPwd) {
        return fs.readFile(
          path.join(__dirname, "../public/accPws.html"),
          "utf8",
          (err, data) => {
            if (err) {
              console.error("err", err);
              return;
            }
            // console.log(data);
            return res.send(data);
          }
        );
      }
    }

    let search_file_Query = `select * from file_info where id = '${fileId}'`;
    // console.log(searchQuery);
    // 查找一下文件表file_info里面的数据是否被删除了？
    let data = await querySql(search_file_Query);
    // console.log("data", data);
    if (!data?.length) {
      return res.status(404).json({
        code: -1,
        msg: `未查找到文件`,
      });
    }
    let contentType = data[0]?.contentType;
    let fileName = data[0]?.fileName;
    // console.log(contentType);

    let file_path = path.join(__dirname, "../", filePath);
    // console.log(file_path);

    // 检查文件是否存在
    fs.access(file_path, fs.constants.F_OK, (err) => {
      // console.log(err);

      if (err) {
        // 如果文件不存在，返回404错误
        return res.status(404).send("未找到文件");
      }
      // 使用createReadStream创建文件读取流
      const readStream = fs.createReadStream(file_path);

      const encodedFileName = `"${encodeURIComponent(fileName)}"`; // 对文件名进行编码并处理引号
      // 设置响应头，指定内容类型和可能的其他选项
      res.setHeader(
        "Content-Type",
        contentType ? contentType : `application/octet-stream`
      ); // 对于未知类型的文件，可以使用octet-stream
      res.setHeader(
        "Content-Disposition",
        `attachment; filename=${encodedFileName}`
      ); // 提示浏览器这是一个下载文件

      // 将文件流连接到响应对象
      readStream.pipe(res);

      // 监听错误事件（可选，但推荐）
      readStream.on("error", (err) => {
        console.error("Error reading file:", err);
        res.status(500).send("Error reading file");
      });
    });
  } catch (err) {
    // console.log("==========getFile(err)============");
    // console.log(err);
    res.status(404).json({
      code: -1,
      msg: `未查找到文件`,
    });
  }
}

module.exports = {
  share,
  getShareFile,
};
